<template>
  <div class="design-shape" :class="{ active: element.focused }" :style="{
    width: `${element.w}px`,
    height: `${element.h}px`,
    top: `${element.y}px`,
    left: `${element.x}px`,
    zIndex: element.z,
    transform: `rotate(${element.r}deg)`,
  }" @mousedown.stop="handleMouseDown" @click="handleContext(element)" @dblclick="dblclick(element)"
    @contextmenu="handleContextMenu($event, element)">
    <template v-if="element.focused">
      <!-- 变换锚点 -->
      <div class="design-shape-point" :ref="name" v-for="(name, index) in point" :key="index" :style="initPoint(name)"
        @mousedown="handleMouseDownOnPoint(name, $event)" />
      <!-- 变换锚点 -->
      <!-- <div
        class="design-shape-point"
        :ref="item"
        v-for="(item, index) in pointList"
        :key="index"
        :style="getPointStyle(item)"
        @mousedown="handleMouseDownOnPointShap(item, $event)"
      /> -->
      <!-- 旋转 -->
      <div class="design-shape-rotate" @mousedown="handleRotate">
        <svg width="14" height="14" xmlns="http://www.w3.org/2000/svg">
          <path
            d="M10.536 3.464A5 5 0 1 0 11 10l1.424 1.425a7 7 0 1 1-.475-9.374L13.659.34A.2.2 0 0 1 14 .483V5.5a.5.5 0 0 1-.5.5H8.483a.2.2 0 0 1-.142-.341l2.195-2.195z"
            fill="#59c7f9" fill-rule="nonzero"></path>
        </svg>
      </div>
    </template>
    <slot></slot>
  </div>
</template>

<script>
import calculateComponentPositonAndSize from "@/utils/calculateComponentPositonAndSize";
export default {
  props: {
    zoom: Number,
    status: {
      type: Boolean,
      default: true,
    },
    element: {
      type: Object,
    },
  },
  data() {
    return {
      pointList: ["lt", "t", "rt", "r", "rb", "b", "lb", "l"], // 八个方向
      point: ["tl", "tr", "br", "bl"],
      isMove: false,
      lineMove: {
        type: null,
        startWidth: 0,
        startHeight: 0,
        startX: 0,
        startY: 0,
        x: 0,
        y: 0,
      },
      // 组件原始的宽高
      origin: null,
      // 光标样式
      cursors: {
        lt: "nw-resize",
        t: "n-resize",
        rt: "ne-resize",
        r: "e-resize",
        rb: "se-resize",
        b: "s-resize",
        lb: "ne-resize",
        l: "w-resize",
      },
    };
  },
  methods: {
    handleContextMenu(e, data) {
      e.stopPropagation();
      e.preventDefault();
      const design = document.getElementById("design");
      const designRect = design.getBoundingClientRect();
      this.$store.dispatch("design/settingMenu", {
        show: true,
        top: e.clientY,
        left: e.clientX - designRect.left,
      });
      this.$store.dispatch("design/selectComplex", data);
    },
    handleContext(data) {
      // 点击事件
      this.$store.dispatch("design/selectComplex", data);
      this.$emit("handleContext", data);
    },
    dblclick(data) {
      this.$store.dispatch("design/selectComplex", data);
      this.$emit("dblclickContext", data);
    },
    // 拖拽顶角手柄事件实现组件缩放
    handleMouseDownOnPointShap(point, e) {
      e.stopPropagation();
      e.preventDefault();

      // 获取画布信息(位置)
      const design = document.getElementById("design");
      const designRect = design.getBoundingClientRect();
      console.log(designRect, "画布信息");

      // 记录鼠标的初始位置和组件的原始宽高
      const startPositon = {
        x: e.clientX,
        y: e.clientY,
        w: this.element.w,
        h: this.element.h,
        left: this.element.x,
        top: this.element.y,
      };
      console.log(startPositon, "鼠标初始位置");

      // 组件的宽高比
      const proportion = this.element.w / this.element.h;
      console.log(proportion, "宽高比");
      console.log(this.element, "组件信息");
      // 组件的中心点
      const center = {
        x: this.element.x + (this.element.w * this.zoom) / 2,
        y: this.element.y + (this.element.h * this.zoom) / 2,
      };
      console.log(center, "中心点");
      // 获取手柄原点的位置信息
      const pointRect = e.target.getBoundingClientRect();
      console.log(pointRect, "手柄原点信息");

      // 当前点击圆点相对于画布的中心坐标的距离
      const curPoint = {
        x: Math.round(
          (pointRect.left - designRect.left) * this.zoom +
          (e.target.offsetWidth * this.zoom) / 2
        ),
        y: Math.round(
          (pointRect.top - designRect.top) * this.zoom +
          (e.target.offsetHeight * this.zoom) / 2
        ),
      };
      console.log(curPoint, "相对于画布的中心坐标的距离");
      // 通过原图形的中心点坐标计算出对称手柄
      const symmetricPoint = {
        x: center.x - (curPoint.x - center.x),
        y: center.y - (curPoint.y - center.y),
      };
      console.log(symmetricPoint, "对称手柄");

      if (this.element.name === "tool-combination") {
        // 记录拖拽前的原始宽高
        this.origin = {
          w: this.element.w,
          h: this.element.h,
        };
        this.$store.dispatch("design/setOrigin", this.origin);
      }

      let isFirst = true;
      const move = (moveEvent) => {
        // 第一次点击时也会触发 move，所以会有“刚点击组件但未移动，组件的大小却改变了”的情况发生
        // 因此第一次点击时不触发 move 事件
        if (isFirst) {
          isFirst = false;
          return;
        }

        // 鼠标当前移动的位置
        const curPositon = {
          x: moveEvent.clientX / this.zoom - Math.round(designRect.left),
          y: moveEvent.clientY / this.zoom - Math.round(designRect.top),
        };

        // console.log(curPositon);

        this.element = calculateComponentPositonAndSize(
          point,
          this.element,
          curPositon,
          proportion,
          false,
          {
            center,
            curPoint,
            symmetricPoint,
          }
        );
      };

      const up = () => {
        // 释放组合元素当前缩放比例
        document.removeEventListener("mousemove", move);
        document.removeEventListener("mouseup", up);

        // 释放组合元素当前缩放比例
        if (this.element.name === "tool-combination") {
          this.updateCombination();
        }
      };

      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", up);
    },
    // 组件变换
    handleMouseDownOnPoint(point, e) {
      e.stopPropagation();
      e.preventDefault();
      // 组件初始宽高
      const startWidth = this.element.w;
      const startHeight = this.element.h;
      const startX = e.clientX;
      const startY = e.clientY;
      const startLeft = this.element.x;
      const startTop = this.element.y;
      if (this.element.name === "tool-combination") {
        console.log("记录拖拽前的原始宽高");
        // 记录拖拽前的原始宽高
        this.origin = {
          w: this.element.w,
          h: this.element.h,
        };
        this.$store.dispatch("design/setOrigin", this.origin);
      }

      // this.cursors = this.getCursor(); // 根据旋转角度获取光标位置
      // 组件宽高比
      const proportion = this.element.w / this.element.h;
      // 组件中心点
      const center = {
        x: this.element.x + this.element.w / 2,
        y: this.element.y + this.element.h / 2,
      };

      const pointRect = e.target.getBoundingClientRect();
      // 当前点击圆点相对于画布的中心坐标
      const designDom = document
        .getElementById("design")
        .getBoundingClientRect();
      const curPoint = {
        x: Math.round(
          pointRect.left - designDom.left + e.target.offsetWidth / 2
        ),
        y: Math.round(
          pointRect.top - designDom.top + e.target.offsetHeight / 2
        ),
      };

      // 获取对称点的坐标
      const symmetricPoint = {
        x: center.x - (curPoint.x - center.x),
        y: center.y - (curPoint.y - center.y),
      };

      let isFirst = true;
      const move = (moveEvent) => {
        // 第一次点击时也会触发 move，所以会有“刚点击组件但未移动，组件的大小却改变了”的情况发生
        // 因此第一次点击时不触发 move 事件
        if (isFirst) {
          isFirst = false;
          return;
        }
        const { clientX, clientY } = moveEvent;
        // 鼠标移动距离
        const moveY = (clientY - startY) / this.zoom;
        const moveX = (clientX - startX) / this.zoom;

        // console.log(moveY, moveX)
        if (point === 'tl') {
          // 左上
          this.element.x = startLeft + moveX;
          this.element.y = startTop + moveY;
          this.element.w = startWidth - moveX;
          this.element.h = startHeight - moveY;
        }

        if (point === 'bl') {
          // 左上
          this.element.x = startLeft + moveX;
          this.element.w = startWidth - moveX;
          this.element.h = startHeight + moveY;
        }

        if (point === 'tr') {
          // 左上
          this.element.y = startTop + moveY;
          this.element.w = startWidth + moveX;
          this.element.h = startHeight - moveY;
        }

        if (point === 'br') {
          // 右下
          this.element.w = startWidth + moveX;
          this.element.h = startHeight + moveY;
        }
      };

      const up = () => {
        document.removeEventListener("mousemove", move);
        document.removeEventListener("mouseup", up);
        console.log(this.element);
        // 释放组合元素当前缩放比例
        if (this.element.name === "tool-combination") {
          this.updateCombination();
        }
      };

      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", up);
    },
    // 修改组合元素子元素的位置宽高值
    updateCombination() {
      // console.log('修改组合元素子元素的位置宽高值')
      const xscale = this.element.w / this.origin.w;
      const yscale = this.element.h / this.origin.h;
      this.element.config.childs.forEach((item, index) => {
        item.x = item.x * xscale;
        item.w = item.w * xscale;
        item.y = item.y * yscale;
        item.h = item.h * yscale;
      });
      this.origin = null;
      this.element.xscale = 1;
      this.element.yscale = 1;
    },
    // 组件移动
    handleMouseDown(event) {
      if (this.element.lock) {
        //组件已锁定
        return;
      }
      const startY = event.clientY;
      const startX = event.clientX;

      const startTop = Number(this.element.y);
      const startLeft = Number(this.element.x);

      const move = (moveEvent) => {
        const curX = moveEvent.clientX;
        const curY = moveEvent.clientY;
        // 设置组件移动位置
        this.element.y = (curY - startY) / this.zoom + startTop;
        this.element.x = (curX - startX) / this.zoom + startLeft;
      };

      const up = () => {
        document.removeEventListener("mousemove", move);
        document.removeEventListener("mouseup", up);
      };

      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", up);
    },
    // 组件旋转
    handleRotate(event) {
      event.preventDefault();
      event.stopPropagation();
      const design = document.getElementById("design");
      let screenTop = design.getBoundingClientRect().top;
      let screenLeft = design.getBoundingClientRect().left;
      // 获取起始点
      const startX = (event.clientX - screenLeft) / this.zoom;
      const startY = (event.clientY - screenTop) / this.zoom;
      // 组件中心点
      const centerX = this.element.x + this.element.w / 2;
      const centerY = this.element.y + this.element.h / 2;

      const startRotate = this.element.r;
      // 旋转前的角度
      const rotateDegreeBefore =
        Math.atan2(startY - centerY, startX - centerX) / (Math.PI / 180);

      const move = (moveEvent) => {
        const curX = (moveEvent.clientX - screenLeft) / this.zoom;
        const curY = (moveEvent.clientY - screenTop) / this.zoom;
        // 旋转后的角度
        const rotateDegreeAfter =
          Math.atan2(curY - centerY, curX - centerX) / (Math.PI / 180);
        // 设置组件旋转角度
        this.element.r = startRotate + rotateDegreeAfter - rotateDegreeBefore;
      };
      const up = () => {
        document.removeEventListener("mousemove", move);
        document.removeEventListener("mouseup", up);
      };
      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", up);
    },
    getPointStyle(point) {
      const width = this.element.w;
      const height = this.element.h;
      const hasT = /t/.test(point);
      const hasB = /b/.test(point);
      const hasL = /l/.test(point);
      const hasR = /r/.test(point);
      let newLeft = 0;
      let newTop = 0;

      // 四个角的点
      if (point.length === 2) {
        newLeft = hasL ? 0 : width;
        newTop = hasT ? 0 : height;
      } else {
        // 上下两点的点，宽度居中
        if (hasT || hasB) {
          newLeft = width / 2;
          newTop = hasT ? 0 : height;
        }

        // 左右两边的点，高度居中
        if (hasL || hasR) {
          newLeft = hasL ? 0 : width;
          newTop = Math.floor(height / 2);
        }
      }

      const style = {
        marginLeft: "-4px",
        marginTop: "-4px",
        left: `${newLeft}px`,
        top: `${newTop}px`,
        cursor: this.cursors[point],
      };

      return style;
    },
    initPoint(name) {
      if (name == "tl") {
        return {
          top: 0,
          left: 0,
          transform: `translate(-50%,-50%)`,
          cursor: `nw-resize`,
        };
      } else if (name == "tr") {
        return {
          top: 0,
          right: 0,
          transform: `translate(50%,-50%)`,
          cursor: `ne-resize`,
        };
      } else if (name == "bl") {
        return {
          bottom: 0,
          left: 0,
          transform: `translate(-50%,50%)`,
          cursor: `ne-resize`,
        };
      } else if (name == "br") {
        return {
          bottom: 0,
          right: 0,
          transform: `translate(50%,50%)`,
          cursor: `se-resize`,
        };
      }
    },
  },
};
</script>

<style lang="scss" scoped>
.design-shape {
  // position: absolute;
  position: fixed;
  box-sizing: border-box;
}

$point-color: #1a1ac7;

.active {
  outline: 1px solid $point-color;
  user-select: none;
}

.design-shape-point {
  position: absolute;
  background: #fff;
  border: 1px solid $point-color;
  width: 8px;
  height: 8px;
  min-width: 8px;
  min-height: 8px;
  border-radius: 50%;
  z-index: 1;
}

.design-shape-rotate {
  position: absolute;
  top: -30px;
  left: 50%;
  transform: translateX(-50%);
  display: inline-block;
  width: 15px;
  height: 15px;
  display: flex;
  justify-content: center;
  align-items: center;
}

.rotate {
  cursor: pointer;
  transform: rotate(45deg);
}
</style>
